
import { mcs8Client } from "./mcs8Client"
import HTTP from "@/utils/request1"
import store from '@/store'

const SLEEP = (delay) => new Promise((resolve) => setTimeout(resolve, delay));

const LOG = (utag, data, cls = false) => {
    var sdata = "";
    if (typeof data == 'object') {
        sdata = JSON.stringify(data);
    } else {
        sdata = data;
    }

    console.log("LOG [%s]%s %o", __KEY__, utag, data);
};

const __KEY__ = 'SdkDemo';

var __GATEWAY_URL__ = null;
var __TOKEN__ = null;
var __REAL_URL__ = "https://sys.mcs8.net:7715";

const __USERNAME__ = 'MKW';
const __PASSWORD__ = 'mcs8@666';

if (process.env.NODE_ENV === 'development') {
    __GATEWAY_URL__ = "/msc8";
} else {
    __GATEWAY_URL__ = __REAL_URL__;
}

/******************************************************
 * MCS8 JavaScript Client SDK 示例
 */
class SdkDemo {
    gatewayUrl = null;
    username = null;
    password = null;
    token = null;

    mClient = null;
    mConnected = false;
    mObserSet = new Map();

    constructor() {
        this.mClient = null;
        this.mConnected = false;
        this.mObserSet = new Map();
    }

    async __initClient(gatewayUrl, username, password, localVideo, localAudio) {

        //调度台地址：https://106.54.78.47:7715

        let url = new URL(gatewayUrl);

        let httpProxy = null;
        if (url.port == "") {
            httpProxy = `:443/gateway`
        } else {
            httpProxy = `:${url.port}/gateway`
        }

        LOG("connect url", url);

        let options = {
            //用户账号配置：支持调度台账号、企业管理员账号，一般使用调度台账号连接网关
            uid: username,                           //调度台用户名
            pwd: password,                           //调度台密码

            localVideo: localVideo,
            localAudio: localAudio,

            //网关连接参数配置，一般情况下使用默认配置即可，非必要不修改
            host: url.hostname,
            port: url.port,
            httpProxy: httpProxy,
            ssl: url.protocol.startsWith("https"),
            privateNet: false,
            encryType: 'v2',
            encryTime: Math.floor(Date.now() / 1000),
        }

        //创建实例
        this.mClient = new mcs8Client();

        //连接网关
        this.mClient.connect(options);

        LOG("connect", options);

        //注册回调，见onReceived
        this.mClient.on('OnManage', this.onReceived.bind(this));
    }

    /****************************************************** */

    //SDK 方法

    /**
     * 连接网关
     * @param {*} gatewayUrl 网关地址
     * @param {*} username 用户名，调度台账号、企业账号，一般为调度台账号
     * @param {*} password 密码
     * @param {*} localVideo 本地Video元素
     * @param {*} localAudio 本地Audio元素
     */
    async connect(username, password, localVideo, localAudio) {
        username = __USERNAME__;
        password = __PASSWORD__;
        let gatewayUrl = __REAL_URL__
        try {
            var url = new URL(gatewayUrl);
        } catch (error) {
            // alert('网关地址错误！');
            console.log('网关地址错误！');
            return {
                success: false,
                msg: '网关地址错误！'
            };
        }

        this.gatewayUrl = gatewayUrl;
        this.username = username;

        this.__initClient(gatewayUrl, username, password, localVideo, localAudio);

        var wait = 5;
        while (!this.mConnected) {
            await SLEEP(500);
            if ((wait--) < 0) {
                break;
            }
        }

        var devStatus = await sdkclient.mClient.requestMsg2GatewayServer("getDevOnlineList", {});
        console.log("devStatus", devStatus);
        await SLEEP(500);

        return this.mConnected;
    }

    /**
     * 关闭连接
     */
    async close() {
        this.mConnected = false;
        if (this.mClient) {
            this.mClient.close();
            this.mClient = null;
        }
    }

    /**
     * 消息回调
     * @param {*} msg
     * @returns
     */
    async onReceived(msg) {

        if (this.mClient == null) {
            return;
        }

        LOG("onReceived", msg.method);

        if (msg.method == 'ConnecteInfo') {
            //连接成功
            __TOKEN__ = msg.data.token;
            this.mConnected = true;
            return;
        } else if (msg.method == 'responseConnectGateway') {
            if (msg.errCode == 200) {
                //ok
            } else if (msg.errCode == 500) {
                // alert('连接服务器失败');
                console.log('连接服务器失败');
                this.close();
            } else {
                // alert('鉴权失败！用户名或密码错误，或无权限。');
                console.log('鉴权失败！用户名或密码错误，或无权限。');
                this.close();
            }
        } else if (msg.method == 'JoinRoomAndProduct') {
            /*创建群组，调度台端一般为收到群组邀请，如设备端发起呼叫
            msg.data = {
                "roomId": "20315664", //组Id
                "TalkGroupType": 5,   //组类型，4：集群对讲组，5：视频组，6：语音组
                "creatorId": "test2", //创建者设备Id，即呼叫方
                "devList": []         //成员
            }*/
        } else if (msg.method == 'joinRoom') {

        } else if (msg.method == 'newPeer') {
            //进入组
        } else if (msg.method == 'peerClosed') {
            //退出组
        } else if (msg.method == 'noAgreeIntoGroup') {
            //拒绝进入组
        } else if (msg.method == 'meetingOut') {
            //解散组
        } else if (msg.method == 'newTalker') {
            //申请发言（成功，正在发言）
        } else if (msg.method == 'freeTalker') {
            //释放发言
        } else if (msg.method == 'gpsUpload') {
            /*设备GPS消息上报，坐标类型：WGS84(大地坐标)：
            msg.data = {
                "devId": "test1", //设备Id
                "gpsTime": "2022-10-24 14:28:37", //定位时间
                "lat": 22.57696333333333, //维度，WGS84(大地坐标)
                "lng": 113.91693500000001, //经度
                "accuracy": 7, //精度（米）
                "speed": 0, //速度（米）
                "direct": 0, //方向
                "netWorkType": 1, //网络类型：1WIFI，2移动网络
                "totalSize": 50319328, //存储容量（字节）
                "useSize": 4209568, //已用容量
                "battery": 71, //电量（%）
            }*/
            store.dispatch('device/haveDeviceGPSChange', msg.data)
        } else if (msg.method == 'DeviceStatus') {
            /*设备状态消息上报，如上线、下线：
            msg.data = {
                "Content": [
                    {
                        "DevId": "test1", //设备Id
                        "Status": 0 //设备状态：0离线，1上线
                    }
                ]
            }
            */
            console.log("DeviceStatus", msg);
            store.dispatch('device/haveDeviceStatusChange', msg.data.Content)
        } else if (msg.method == 'AlarmUpload') {
            /*设备报警消息上报，如SOS：
            msg.data = {
                "devId": "test1", //设备Id
                "enterId": 20000000, //企业Id
                "groupId": 30000000, //组Id
                "peopleNo": "000000", //人员编号
                "workNo": "8600021935078769", //工单编号
                "alarmType": 2, //报警类型，见《1.8.报警信息上报》
                "alarmTime": "2022-10-24 15:36:36", //报警时间
                "alarmDesc": "sos", //报警描述
                "status": 1, //报警状态：0无（无开始和结束标识），1开始报警，2结束报警
                "GPSModel": { //报警位置
                    "gpsTime": "1970-01-01 08:00:00",
                    "lat": "0.0",
                    "lng": "0.0",
                    "netWorkType": 1
                },
            }*/
        } else if (msg.method == 'logoutByOtherLogin') {
            //踢出（异地登录）
            console.log('踢出（异地登录）');
            this.close();
        } else {
            return;
        }

        LOG("onReceived", msg);

        this.notifyAllObserver(msg);
    }

    /**
     * 发送消息》网关
     * @param {*} method 命令字
     * @param {*} data 消息数据体
     * @returns
     */
    async requestMsg2GatewayServer(method, data) {
        LOG(`requestMsg2GatewayServer method=${method}`, data);

        let r = await this.mClient.requestMsg2GatewayServer(method, data);
        LOG(`requestMsg2GatewayServer method=${method} resp=`, r);

        return r;
    }

    /****************************************************** */
    //SDK & 观察者封装

    addObserver(key, fn) {
        this.mObserSet.set(key, fn);
    }

    removeObserver(key) {
        this.mObserSet.delete(key);
    }

    notifyAllObserver(request) {
        for (var [key, fn] of this.mObserSet) {
            fn.call(this, request);
        }
    }
}

/******************************************************
 * pages FUNC
 */
let sdkclient = new SdkDemo()


/**
 * 获取sdk客户端
 * @returns sdkclient
 */
function getSdkClient() {
    if (sdkclient == null) {
        sdkclient = new SdkDemo();
    }
    return sdkclient;
}

/**
 * 初始化模块：获取设备列表（全部）
 * @param {*} key
 */
async function FUNC_init_getDevList(key) {


    if (sdkclient.mConnected) {

        var devStatus = await sdkclient.mClient.requestMsg2GatewayServer("getDevOnlineList", {});

        // var url = `${__GATEWAY_URL__.replace("gateway", "")}/api/v1/ext/DevTree?token=${__TOKEN__}`;

        let resp = await HTTP({
            baseURL: __GATEWAY_URL__,
            url: `/api/v1/ext/DevTree?token=${__TOKEN__}`,
            method: 'get',
            headers: {
                "token": __TOKEN__,
                'Content-Type': 'application/json'
            },
        })
        var data = [];

        if (resp.result == 0 || resp.result == 200) {

            for (const item of resp.content) {

                var pId = item.pid;
                if (item.type == 1 && pId == 0) { //type=1企业
                }
                if (item.type == 2 && pId == 0) { //type=2固定组
                    var findEnter = resp.content.find(p => p.type == 1 && p.id == item.data.enterId);
                    if (findEnter) {
                        pId = findEnter.id;
                    }
                }
                if (item.type == 3 && pId == 0) { //type=3终端设备
                    var findEnter = resp.content.find(p => p.type == 1 && p.id == item.data.enterId);
                    if (findEnter) {
                        pId = findEnter.id;
                    }
                }

                var name = item.text;
                if (item.type == 1) {
                    name = '[企业]' + name
                } else if (item.type == 2) {
                    name = '[固定组]' + name
                } else if (item.type == 3) {
                    if (item.data.deviceType == '2') {
                        name = '[调度台]' + name;
                    } else {
                        name = '[设备]' + name;
                    }
                    var find = devStatus.Content.find(p => p.DevId == item.data.deviceId);
                    if (find) {
                        item.data.status = 1;
                        name = name + '(在线)';
                    } else {
                        item.data.status = 0;
                        name = name + '(离线)';
                    }
                }

                data.push({
                    ...item,
                    pId,
                    name,
                    open: (item.type == 1)
                });

                //多路处理
                if (item.type == 3 && item.data.deviceType == '5' || item.data.deviceType == '11') {
                    if (Array.isArray(item.extras)) {
                        for (const devCh of item.extras) {
                            data.push({
                                ...item,
                                id: devCh.id,
                                pId: item.id,
                                name: '[通道]' + devCh.name,
                                channelId: devCh.code,
                                channelName: devCh.name
                            });
                        }
                    }
                }
            }
        }
        return data;
    } else {
        return [];
    }
}

/**
 * 初始化模块：获取在线设备列表
 * @param {*} key
 */
function FUNC_init_getDevOnlineList(key) {

    if (sdkclient.mConnected) {
        sdkclient.mClient.requestMsg2GatewayServer("getDevOnlineList", {}).then(resp => {
            LOG('getDevOnlineList', resp);

            /*获取在线设备列表，Status：状态，0离线，1在线（仅返回在线设备） ：
            resp.Content = [
                {
                    "DevId": "pc1",
                    "Status": 1
                },
                {
                    "DevId": "test1",
                    "Status": 1
                }
            ]*/

            var data = { list: resp.Content };
            // var html = template(`tpl_${key}`, data);
            // document.getElementById(`tpl_${key}_content`).innerHTML = html;
        })
    }
}

// ===================================>实时视频<=======================================
/**
 * 打开实时视频
 * @param {*} devId 设备Id
 * @param {*} channelId 通道号（非多通道设备为null）
 */
async function FUNC_openVideo(devId, channelId) {
    var remoteVideo = document.getElementById(`remoteVideo${devId}`);
    console.log('FUNC_openVideo', document.getElementById(`remoteVideo${devId}`));
    var resp = await sdkclient.mClient.openVideo(devId, remoteVideo, channelId, null);//设备Id,HTMLVideo对象,设备通道（可为null），服务器Id(一般不需要使用)

    LOG('openVideo', resp);
}

/**
 * 关闭实时视频
 * @param {*} devId 设备Id
 * @param {*} channelId 通道号（非多通道设备为null）
 */
async function FUNC_closeVideo(devId, channelId) {
    var resp = await sdkclient.mClient.closeVideo(devId, channelId);//设备Id,设备通道（可为null），服务器Id(一般不需要使用)

    LOG('closeVideo', resp);
}

/**
 * 打开声音监听
 * @param {*} devId 设备Id
 * @param {*} channelId 通道号（非多通道设备为null）
 */
async function FUNC_openAudio(devId, channelId) {
    var remoteAudio = document.getElementById(`remoteAudio${devId}`);
    var resp = await sdkclient.mClient.openAudio(devId, remoteAudio, channelId);//设备Id,HTMLAudio对象,设备通道（可为null），服务器Id(一般不需要使用)

    LOG('openAudio', resp);
}

/**
 * 关闭声音监听
 * @param {*} devId 设备Id
 * @param {*} channelId 通道号（非多通道设备为null）
 */
async function FUNC_closeAudio(devId, channelId) {
    var resp = await sdkclient.mClient.closeAudio(devId, channelId);//设备Id,设备通道（可为null），服务器Id(一般不需要使用)

    LOG('closeAudio', resp);
}

// ===================================>视频通话<=======================================
/**
 * 创建双向视频通话组
 * @param {*} devId
 */
async function FUNC_CreateP2pMediaGroup(devId) {
    var groupId = __FUNC_CreateRandomGroupId(devId);
    var groupType = 5; //组类型，4：集群对讲组，5：视频组，6：语音组

    if (await sdkclient.mClient.checkInputDevice(groupType) == 404) {
        // alert('该功能需要麦克风（USB耳麦）、摄像头支持！');
        console.log('该功能需要麦克风（USB耳麦）、摄像头支持！');
        return;
    }
    console.log("打开视频通话", document.getElementById(`remoteVideo${devId}`));
    var devModel = { kind: 'video', devId, showObj: document.getElementById(`remoteVideo${devId}`) }
    var resp = await sdkclient.mClient.CreateP2pMediaGroup(groupId, groupType, devModel);

    LOG('CreateP2pMediaGroup', resp);

    //监听进入组回调，关联音频元素，见onReceived说明
    sdkclient.addObserver('CreateP2pMediaGroup', msg => {
        console.log(`remoteAudio${msg.data.id}`,"1111111111111111111111111");
        console.log(msg,"1111111111111111111111111");
        if (msg.method == 'newPeer') {
            sdkclient.mClient.addShowObject({
                groupId: __randomGroupIdMap[devId],
                kind: 'audio',
                devId: msg.data.id,
                showObj: document.getElementById(`remoteAudio${msg.data.id}`)
            });
        }
    })
}

// ===================================>语音通话<=======================================
/**
* 创建双向语音通话组
* @param {*} devId
*/
async function FUNC_CreateP2pMediaGroup6(devId) {
    console.log(devId);
    var groupId = __FUNC_CreateRandomGroupId(devId);
    var groupType = 6; //组类型，4：集群对讲组，5：视频组，6：语音组

    if (await sdkclient.mClient.checkInputDevice(groupType) == 404) {
        // alert('该功能需要麦克风（USB耳麦）支持！');
        console.log('该功能需要麦克风（USB耳麦）支持！');
        return;
    }

    var devModel = { kind: 'audio', devId, showObj: document.getElementById(`remoteAudio${devId}`) }
    var resp = await sdkclient.mClient.CreateP2pMediaGroup(groupId, groupType, devModel);

    LOG('CreateP2pMediaGroup', resp);
}

/**
 * 关闭通话组
 */
async function FUNC_closeGroup(devId, groupId = 0) {

    sdkclient.removeObserver("CreateP2pMediaGroup");

    if (groupId == 0) {
        groupId = __randomGroupIdMap[devId]
    }

    var resp = await sdkclient.mClient.closeGroup(groupId);

    LOG('closeGroup', resp);
}

var __randomGroupIdMap = {};


/**
 * 获取通话组Id：不重复即可
 * @param {*} devId
 * @returns
 */
function __FUNC_CreateRandomGroupId(devId, groupId = 0) {
    if (devId == undefined) {
        devId = "temp";
    }

    if (groupId > 0) {
        __randomGroupIdMap[devId] = groupId;
    } else {
        __randomGroupIdMap[devId] = Date.parse(new Date()).toString();
    }

    return __randomGroupIdMap[devId];
}

/**
 * 获取通话组Id：不重复即可
 * @returns
 */
function FUNC_GPS_LIST(data) {
    return HTTP({
        baseURL: __GATEWAY_URL__,
        url: '/api/v1/GPSList',
        method: 'get',
        params: data,
        headers: {
            "token": __TOKEN__,
            'Content-Type': 'application/json'
        },
    })
}

export default {
    FUNC_init_getDevList,
    FUNC_init_getDevOnlineList,
    sdkclient,
    FUNC_openVideo,
    FUNC_CreateP2pMediaGroup,
    FUNC_closeVideo,
    FUNC_openAudio,
    FUNC_closeAudio,
    FUNC_CreateP2pMediaGroup6,
    FUNC_GPS_LIST,
    FUNC_closeGroup
}